import axios, { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import { ApiResponse } from '../type/request'
import {
  ACCESS_TOKEN,
  ACCESS_TOKEN_EXPIRE_TIME,
  APP_NAME,
  REFRESH_TOKEN,
  REFRESH_TOKEN_EXPIRE_TIME,
  USER_ID,
} from '../const'
import { AuthService } from '../auth/service'
import { getBaseUrl } from '../dev/config/index.ts'
import { getStorageItem } from '../base/storage'

interface CustomRequestConfig extends AxiosRequestConfig {
  requestId?: string
  fullResponse?: boolean
}

// 辅助类型：提取 ApiResponse 中 data 字段的类型
type ExtractData<T> = T extends { data?: infer U } ? U : T extends { data: infer U } ? U : never

// 条件类型：根据 fullResponse 返回不同的类型
type ResponseType<T, F extends boolean | undefined> = F extends true ? T : ExtractData<T>

// 定义 auth handler 类型
type AuthHandler = {
  login: (tokens: Auth.AuthTokens) => void
  logout: (redirectUrl?: string) => void
  navigateToLogin: (redirectUrl?: string) => void
} | null

// const LocalStorageMockData: Record<string, string> = {
//   _accessToken:
//     'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiI1NTQwMTA4NzQ3NzAwMDExOCIsInJuU3RyIjoidGpxOVlpejNBelEzc1N4RGdTaHVFUktyRlJsRWl3QWsiLCJlZmYiOjE3NDQ1MjczMjE1NzEsImFwcE5hbWUiOiJEcmVhbW9uYSJ9.cIKln6TB9bOeJHzwhAiFnDKp6AtYquQpXpsS8AGIrzQ',
//   _expiresIn: '1744527321711',
//   _refreshExpiresIn: '1749711321711',
//   _refresh_token:
//     'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiI1NTQwMTA4NzQ3NzAwMDExOCIsImRldmljZSI6ImRldmljZSIsImVmZiI6MTc0OTcxMTMyMTU3MSwicm5TdHIiOiJreTFLcnJrcUpNRGdPMWVLWXNLYXdmTDhVVEQ5MTh4ZyIsImFwcE5hbWUiOiJEcmVhbW9uYSJ9.k8g2Niwq2WlqTpsgCefJlV1hVWFHP6UPE2HQbN_o_dw',
//   _userId: '55401087477000118',
//   _user_avatar: 'https://lh3.googleusercontent.com/a/ACg8ocLJhAcdkxf83Pzdi0dYYc0bucyHn1lwB8tOoF7ilbYAgllhWvM=s96-c',
//   _user_email: 'wu96year@gmail.com',
//   pending_ad_sources: '{}',
// }

// // 如果是本地开发环境
// if (typeof window !== 'undefined' && window.localStorage && process.env.NODE_ENV === 'development') {
//   Object.keys(LocalStorageMockData).forEach(key => {
//     localStorage.setItem(key, LocalStorageMockData[key])
//   })

//   console.log('测试环境数据已写入本地开发环境！')
// }

// 在文件开头添加 Cookie 和 Safari 检测函数
const isSafari = () => {
  if (typeof navigator === 'undefined') return false
  const ua = navigator.userAgent.toLowerCase()
  return ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1 && ua.indexOf('android') === -1
}

const getCookie = (name: string): string | null => {
  if (typeof document === 'undefined') return null
  const nameEQ = name + '='
  const ca = document.cookie.split(';')
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i]
    while (c.charAt(0) === ' ') c = c.substring(1, c.length)
    if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length))
  }
  return null
}

class HttpClient {
  private instance: AxiosInstance
  private abortControllers: Map<string, AbortController>
  private static authHandler: AuthHandler = null
  private request401Count: number = 0 // 统计401错误次数
  private maxRequest401Count: number = 20

  // 静态方法设置 auth handler
  public static setAuthHandler(handler: AuthHandler) {
    HttpClient.authHandler = handler
  }

  constructor() {
    this.instance = axios.create({
      // baseURL路径，由部署环境决定
      baseURL: getBaseUrl(),
      headers: {
        'Content-Type': 'application/json',
        'ts-app-name': APP_NAME,
        // 无多语言，暂定英语
        lang: 'en-US',
      },
      timeout: 20 * 1000,
    })
    this.abortControllers = new Map()
    this.setupInterceptors()
  }

  private async checkAndRefreshTokens(): Promise<string | null> {
    // 如果不是浏览器环境，直接返回null
    if (typeof window === 'undefined') {
      return null
    }

    const accessToken = getStorageItem(ACCESS_TOKEN)
    const refreshToken = getStorageItem(REFRESH_TOKEN)
    const accessTokenExpireTime = getStorageItem(ACCESS_TOKEN_EXPIRE_TIME)
    const refreshTokenExpireTime = getStorageItem(REFRESH_TOKEN_EXPIRE_TIME)

    const currentTime = Date.now()

    // 如果没有token，直接返回null
    if (!accessToken || !refreshToken) {
      return null
    }

    // 检查access token是否过期
    if (accessTokenExpireTime && currentTime < parseInt(accessTokenExpireTime)) {
      console.log('accessToken not expired:', accessToken)
      // access token 未过期，直接返回
      return accessToken
    }

    // access token已过期，检查refresh token是否过期
    if (refreshTokenExpireTime && currentTime < parseInt(refreshTokenExpireTime)) {
      try {
        // 使用refresh token获取新的token
        const response = await AuthService.getUserToken({
          grantType: 'refreshToken',
          appName: APP_NAME,
          refreshToken: refreshToken,
          userType: 'app_user',
        })

        // 使用AuthProvider的login方法更新token
        HttpClient.authHandler?.login(response)

        return response.accessToken
      } catch (error) {
        console.error('Failed to refresh token:', error)
        // 刷新失败，执行登出
        HttpClient.authHandler?.logout('/login')
        return null
      }
    } else {
      // refresh token也过期了，执行登出
      HttpClient.authHandler?.logout('/login')
      return null
    }
  }

  private generateRequestId(): string {
    return Math.random().toString(36).substring(7)
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(async (config: CustomRequestConfig & InternalAxiosRequestConfig) => {
      // Ensure headers are defined
      config.headers = config.headers || {}

      // 只在浏览器环境下获取userId
      if (typeof window !== 'undefined' && window.localStorage) {
        const userId = localStorage.getItem(USER_ID)
        userId && (config.headers['ts-user-id'] = userId)
      }

      try {
        const validToken = await this.checkAndRefreshTokens()
        if (validToken) {
          // config.headers.Authorization = `Bearer ${validToken}`
        }
      } catch (error) {
        console.error('Token check failed:', error)
      }

      let url = config.url || ''
      const params = config.params || {}

      // 处理 URL 参数
      url = url.replace(/{(\w+)}/g, (match, key) => {
        if (params[key]) {
          const value = params[key]
          delete params[key]
          return encodeURIComponent(value)
        }
        return match
      })

      // 处理 RESTful 方法
      const urlConfig = url.split(/\s+/)
      if (urlConfig.length > 1) {
        config.method = urlConfig[0].toLowerCase()
        url = urlConfig[1]
      }

      // 为每个请求创建独立的 AbortController
      const requestId = this.generateRequestId()
      const controller = new AbortController()
      this.abortControllers.set(requestId, controller)
      config.signal = controller.signal
      config.requestId = requestId

      config.url = url
      return config
    })

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        // 重置401错误计数
        this.request401Count = 0

        // 请求完成后，删除对应的 AbortController
        const requestId = (response.config as CustomRequestConfig)?.requestId
        if (requestId) {
          this.abortControllers.delete(requestId)
        }

        const { code, data, message, msg } = response.data

        // 如果需要返回完整数据响应
        if ((response.config as CustomRequestConfig)?.fullResponse) {
          return response.data
        }

        // 这里默认返回data,业务正常
        if (code === 0) {
          return (response.config as CustomRequestConfig)?.fullResponse ? response.data : data
        } else {
          // showNotification({
          //   message: message || msg || '接口错误',
          //   type: 'error',
          // })
          return Promise.reject(response.data)
        }
      },
      async error => {
        // 请求出错时，也需要删除对应的 AbortController
        if (error.config?.requestId) {
          this.abortControllers.delete(error.config.requestId)
        }

        console.log('Request error:', error, error.response?.status)

        if (axios.isAxiosError(error) && error.response?.status === 401) {
          this.request401Count++ // 增加401错误计数
          if (this.request401Count > this.maxRequest401Count) {
            HttpClient.authHandler?.logout()
            return Promise.reject(new Error('Too many 401 errors, user logged out.'))
          }

          try {
            const validToken = await this.checkAndRefreshTokens()
            if (validToken && error.config) {
              // 如果成功获取新token，重试失败的请求
              // error.config.headers.Authorization = `Bearer ${validToken}`
              return this.instance.request(error.config)
            } else {
              console.error('validToken failed, navigate to login')
              HttpClient.authHandler?.navigateToLogin()
            }
          } catch (refreshError) {
            console.error('Token refresh failed:', refreshError)
            HttpClient.authHandler?.navigateToLogin()
          }
        } else {
          if (axios.isAxiosError(error)) {
            // showNotification({
            //   message: error.message || '接口异常',
            //   type: 'error',
            // })
          }
        }

        return Promise.reject(error)
      }
    )
  }

  // 取消指定请求
  abort(requestId: string) {
    const controller = this.abortControllers.get(requestId)
    if (controller) {
      controller.abort()
      this.abortControllers.delete(requestId)
    }
  }

  // 取消所有请求
  abortAll() {
    this.abortControllers.forEach(controller => {
      controller.abort()
    })
    this.abortControllers.clear()
  }

  // 请求方法

  //   // RESTful 方法示例
  // httpClient.request({
  //   url: 'POST /api/users'  // 直接在 URL 中指定方法
  //   data: { name: 'John' }
  // });
  // // 最终请求: POST /api/users
  request<TResponse extends ApiResponse, TFullResponse extends boolean | undefined = false>(
    config: CustomRequestConfig & { fullResponse?: TFullResponse }
  ): Promise<{
    data: ResponseType<TResponse, TFullResponse>
    requestId: string
  }> {
    const requestId = this.generateRequestId()
    config.requestId = requestId
    return this.instance.request<TResponse>(config).then(response => {
      // 响应拦截器已经处理了 fullResponse 逻辑，这里直接使用 response
      return {
        data: response as ResponseType<TResponse, TFullResponse>,
        requestId,
      }
    })
  }

  // // URL 参数示例
  // httpClient.get('/api/users/{id}/posts', {
  //   params: {
  //     id: '123',
  //     page: 1  // 这个会作为查询参数保留
  //   }
  // });
  // // 最终请求: GET /api/users/123/posts?page=1
  get<TResponse extends ApiResponse, TFullResponse extends boolean | undefined = false>(
    url: string,
    config: CustomRequestConfig & { fullResponse?: TFullResponse } = {
      headers: {},
    }
  ): Promise<{
    data: ResponseType<TResponse, TFullResponse>
    requestId: string
  }> {
    config.headers = config.headers || {}
    const requestId = this.generateRequestId()
    config.requestId = requestId
    return this.instance.get<TResponse>(url, config).then(response => {
      return {
        data: response as ResponseType<TResponse, TFullResponse>,
        requestId,
      }
    })
  }

  post<TResponse extends ApiResponse, TFullResponse extends boolean | undefined = false>(
    url: string,
    data?: any,
    config: CustomRequestConfig & { fullResponse?: TFullResponse } = {
      headers: {},
    }
  ): Promise<{
    data: ResponseType<TResponse, TFullResponse>
    requestId: string
  }> {
    config.headers = config.headers || {}
    const requestId = this.generateRequestId()
    config.requestId = requestId
    return this.instance.post<TResponse>(url, data, config).then(response => {
      return {
        data: response as ResponseType<TResponse, TFullResponse>,
        requestId,
      }
    })
  }
}

// 导出实例
export const httpClient = new HttpClient()
export const setAuthHandler = HttpClient.setAuthHandler
